#include <iostream>
using namespace std;

class A{
public: A(int a):_a(a)
  {

  }
private :
 int _a;
};
class Date
{

public:
friend ostream& operator<<(ostream& out,const Date& d) ;
friend istream& operator>>(istream& in,Date& d);
// 获取某年某月的天数
int GetMonthDay(int year, int month)const
{
    if(month>12 || month<1)
    {
        printf("the GetMonthDay error :Month illegal\n");
        return 0;
    }
    static int arr[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
    if((year %4 == 0 && year%100 != 0 || year%400==0) && month ==2)
    {
        return 29;
    }
    return arr[month-1];
}


  // 全缺省的构造函数

Date(int year = 1900, int month = 1, int day = 1) //给默认值要给就给在声明
//初始化列表是成员定义的地方，我们直到定义自定义类型就会自动调用构造函数
: _year(year),
_month(month),
_day(day),//这里才是类里面所所声明变量的定义
_a(1)//如果A对象有默认值，那么这里不显性调用也可以,这里即使不对其初始化也依然会对构造函数进行调用，因为会自动调用自定义类型的构造函数
{
    if(month>12 || month<1 )
    {
        printf("the GetMonthDay error :Month illegal\n");
    }
    if(GetMonthDay(year,month)<day || day<1)
    {
      printf("the GetMonthDay error :Day illegal\n");
    }
    this->_year = year;//这些操作都叫做赋值
    this->_month = month;
    this->_day = day;
}

void print() const
{
    cout<<_year<<"/"<<this->_month<<"/"<<this->_day<<endl;
}

  // 拷贝构造函数

// d2(d1)

Date(const Date& d) //这里只允许引用，否则进行传参就会无穷递归
:_a(1)//拷贝构造函数也同理
{
    this->_year = d._year;
    this->_day = d._day;
    this->_month = d._month;
}

   

  // 赋值运算符重载

// d2 = d3 -> d2.operator=(&d2, d3)

Date& operator=(const Date& d)
{
    if(&d == this)
    {
        return *this;
    }
    this->_year = d._year;
    this->_month = d._month;
    this->_day = d._day;
    return *this;//返回this指针的解引用
}//赋值重载，主要用于把一个类的给另外一个类
    //一般来说，这里面存在的就是浅拷贝，比如给指针赋值，就是让指针指向同一块空间。



  // 析构函数

~Date()//如果再类里面有申请了堆上的空间，需要释放
{
    this->_year = 0;
    this->_day = 0;
    this->_month = 0;
}



  // 日期+=天数

Date& operator+=(int day)
{
    this->_day += day;
    while(this->_day>GetMonthDay(this->_year,this->_month))
    {
        this->_day -= GetMonthDay(this->_year,this->_month);
        this->_month++;
        if(this->_month>12)
        {
            this->_month = 1;
            this->_year++;
        }
    }
    return *this;
}



  // 日期+天数

Date operator+(int day)const
{
    Date d = *this;
    d += day;
    return d;
}



  // 日期-天数

Date operator-(int day)const
{
    Date d = *this;
    d -= day;
    return d;
}



   // 日期-=天数

Date& operator-=(int day)
{
    this->_day -= day;
    while(this->_day<=0)
    {
        this->_month--;
        if(this->_month<=0)
        {
            this->_month = 12;
            this->_year--;
        }
        this->_day += GetMonthDay(this->_year,this->_month);
    }
    return *this;
}



  // 前置++

Date& operator++()
{
    (*this)+=1;
    return *this;
}



  // 后置++

Date operator++(int)
{
    Date d = (*this);
    (*this)+=1;
    return d;
}



  // 后置--

Date operator--(int)
{
    Date d = (*this);
    (*this)-=1;
    return d;
}



  // 前置--

Date& operator--()
{
    (*this)-=1;
    return *this;
}



  // >运算符重载

bool operator>(const Date& d)const
{
    return this->_year>d._year && this->_month > d._month && this->_day>d._day;
}



  // ==运算符重载

bool operator==(const Date& d)const
{
    return this->_year==d._year && this->_month == d._month && this->_day==d._day;
}



  // >=运算符重载

bool operator >= (const Date& d)const
{
    return this->operator>(d) || this->operator==(d);
}

   

  // <运算符重载

bool operator < (const Date& d)const
{
    return this->_year<d._year && this->_month < d._month && this->_day<d._day;
}



   // <=运算符重载

bool operator <= (const Date& d)const
{
    return this->operator<(d) || this->operator==(d);
}



  // !=运算符重载

bool operator != (const Date& d)const
{
    return !(this->operator==(d));
}



  // 日期-日期 返回天数

int operator-(const Date& d)const
{
    int year =  (this->_year - d._year)*365 +(this->_year - d._year)/4 - (this->_year - d._year)/100 +(this->_year - d._year)/400;
    int month1 =0;
    for(int i=1;i<this->_month;i++)
    {
        month1+= GetMonthDay(_year,i);
    }
    int month2 = 0;
    for(int i=1;i<d._month;i++)
    {
        month2+= GetMonthDay(d._year,i);
    }
    int day =  (this->_day - d._day);
    return year-month2+month1 +day;
}

Date* operator&()
{
    return this;
}
const Date* operator&() const
{
    return this;
}//这里就是const修饰的this指针的一种应用场景


//变量的声明
private:

int _year;

int _month;

int _day = 11;//c++11支持这里给缺省值，就是默认在初始化列表给这个缺省值

A _a;
//初始化列表的时候，是按照声明一次初始化，不是按照初始化列表处的写法。
};


ostream& operator<<(ostream& out,const Date& d) //类实现流插入
//这里就是友元函数一种使用场景，就是函数需要在类外部，但是又要直接用类的私有成员，那么用友元函数就会很方便

{
    out<<d._year<<"/"<<d._month<<"/"<<d._day<<endl;
    return out;
}

istream& operator>>(istream& in,Date& d) 
{
    in >> d._year >> d._month >>d._day;//流插入空格换行分割
    if(d.GetMonthDay(d._year,d._month)<d._day || d._day<1)
    {
      printf("the GetMonthDay error :Day illegal\n");
    }
    return in;
}
// int main()
// {
//     Date d(2023,7,30);
//     cin >> d;
//     return 0;
// }